package com.example.douyin.controller;

import com.alibaba.fastjson.JSON;
import com.example.douyin.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.http.*;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static org.springframework.http.HttpHeaders.SET_COOKIE;

/**
 * @author: dangwen
 * @createDate: 2020/11/30
 */
@Controller
@ResponseBody
@Slf4j
public class AuthorizationController {

    /**
     * 1.@Resource的作用相当于@Autowired，只不过@Autowired按byType自动注入，而@Resource默认按 byName自动注入罢了
     */
    @Resource
    private RestTemplate restTemplate;

    @GetMapping("getUserCode")
    public void getUserCode(HttpServletResponse response) throws IOException {
        // redirect_uri 应为具体处理接口
        String url = "https://open.douyin.com/platform/oauth/connect?client_key=awlrwv8p9pq6wa20&response_type=code&scope=user_info&redirect_uri=http://easemob.com/";
        response.sendRedirect(url);
    }

    @GetMapping("getUserInfo")
    public UserInfoRespDataVo getUserInfo(String code){
        String tokenUrl = "https://open.douyin.com/oauth/access_token?client_key=awlrwv8p9pq6wa20&client_secret=bc4302bb938e81dc7cbfd94fea4a0e06&code="
                + code + "&grant_type=authorization_code";
//        String access_token = restTemplate.getForObject(url, String.class);
        ResponseEntity<RespVo> accessToken = restTemplate.getForEntity(tokenUrl, RespVo.class);
        RespVo accessTokenBody = accessToken.getBody();
        AccessTokenRespDataVo accessTokenBodyData = (AccessTokenRespDataVo) accessTokenBody.getData();
        String infoUrl = "https://open.douyin.com/oauth/userinfo?open_id=" + accessTokenBodyData.getOpen_id() + "&access_token=" + accessTokenBodyData.getAccess_token();
        ResponseEntity<RespVo> userInfo = restTemplate.getForEntity(infoUrl, RespVo.class);
        RespVo userInfoBody = userInfo.getBody();
        UserInfoRespDataVo userInfoBodyData = (UserInfoRespDataVo) userInfoBody.getData();
        return userInfoBodyData;
    }

    @GetMapping("refreshToken")
    public RespVo refreshToken(String client_key, String refresh_token){
        String refreshUrl = "https://open.douyin.com/oauth/renew_refresh_token?client_key=" + client_key + "&refresh_token=" + refresh_token;
        ResponseEntity<RespVo> forEntity = restTemplate.getForEntity(refreshUrl, RespVo.class);
        RespVo body = forEntity.getBody();
        return body;
    }

    // https://www.easemob.com/?code=co1GnH3vCaWIP7tDAT98ltvP95imopofsKe7&state=
    @GetMapping("parameter")
    public void getParameter(HttpServletRequest request){
        Map<String, String[]> parameterMap = request.getParameterMap();
        String[] codes = parameterMap.get("code");
        System.out.println(codes[0]);
    }

    @GetMapping("postLogin")
    public String postLogin(){
        String url = "http://127.0.0.1:8080/login";
        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("username","dangwen");
        map.add("password","123456");
        HttpHeaders httpHeaders = new HttpHeaders();
        // 模拟form表单发送请求
        httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, httpHeaders);
        return restTemplate.postForObject(url, request, String.class);
    }

    @GetMapping("loginTest")
    public String loginTest(){
        String s2 = "YUhSMGNEb3ZMM056WVM1cVpDNWpiMjB2YzNOdkwyeHZaMmx1enp6";
        String url = getUrl(s2);
        String password = "Kk4lgZ+KsczJHTGKzisRflTCGwfFog1kmkSpGkOSVotDCmi+v4qoE656C/CTU7Qw4SCIjWD2S9aKRTg+Nb4kD+uz0eiy2PdJ25QgD+4WrW2THM9mRfHmo4RNcgnl2ryCeDKpiv3rPR9Rds8JO0CuSdz6ENLiUjZ+k2YiCR4VT2I=";
        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("username","dangwen1");
        map.add("password",password);
        map.add("fp","OFK4DIXYKCWGRB4WBTEPDQSOYIMFVFSL6XIL2IKH5JNRO45NK2YUCCUKDCCEMZYNGGXBQ22U3TXBTXU3K3ZPQDSYVA");
        map.add("uuid","4b5b093e021043e795b3d3b713d3db86");
        HttpHeaders httpHeaders = new HttpHeaders();
        // 模拟form表单发送请求
        httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, httpHeaders);
        // postForObject这个方法返回的结果是响应体中内容，不包括header，如果想获得header，需要使用exchange方法
//        Object o = restTemplate.postForObject(url, request, Object.class);
        ResponseEntity<Object> exchange = restTemplate.exchange(url, HttpMethod.POST, request, Object.class);
        HttpHeaders headers = exchange.getHeaders();
        List<String> list = headers.get(SET_COOKIE);
        return beforSignIn(list);
    }

    private String getUrl(String s2) {
        byte[] bytes = Base64.decodeBase64(s2);
        String s3 = new String(bytes);
        String s4 = s3.replace("zzz", "");
        return new String(Base64.decodeBase64(s4));
    }

    public String beforSignIn(List<String> list){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = simpleDateFormat.format(new Date());
        log.info("signTime：{}",format);
        String s2 = "YUhSMGNEb3ZMMlZ5Y0M1cVpDNWpiMjB2Y0c5eWRHRnNMMk5zYjJOckwyTnNiMk5yU1c1bWJ3PT16eno=";
        String url = getUrl(s2);
        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        HttpHeaders httpHeaders = new HttpHeaders();
        // 模拟form表单发送请求
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        String cookie = null;
        String s3 = "YzNOdkxtcGtMbU52YlE9PXp6eg==";
        for (String s : list) {
            if (s.startsWith(getUrl(s3))){
                cookie = s;
            }
        }
        httpHeaders.set("cookie",cookie);
        HttpEntity<MultiValueMap<String, String>> tsDateRequest = new HttpEntity<>(map, httpHeaders);
        ResponseBodyVO responseBodyVO = restTemplate.postForObject(url, tsDateRequest, ResponseBodyVO.class);
        DataVO dataVO = null;
        if (Objects.nonNull(responseBodyVO)) {
            dataVO = responseBodyVO.getData();
        }
        return signIn(cookie, dataVO);
    }

    public String signIn(String cookie, DataVO data){
        if (data == null){
            return "传入的data不能为空";
        }
        String s2 = "YUhSMGNEb3ZMMnRoYjNGcGJpNXFaQzVqYjIwdmEyRnZjV2x1TDJOb1pXTnJTVzVLYzI5dWNEOTBjMFJoZEdVOXp6eg==";
        String url = getUrl(s2);
        String s3 = "Sm5SelJHRjBaVVJsY3owPXp6eg==";
        String param = getUrl(s3);
        String signUrl = url + data.getTsDate() + param + data.getTsDateDes() +
                "&_=" + System.currentTimeMillis();
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("cookie", cookie);
        HttpEntity<String> httpEntity = new HttpEntity<>(httpHeaders);
        // get请求如果想要设置请求头，需要使用exchange方法，因为getForxx方法不支持请求头
        ResponseEntity<String> exchange = restTemplate.exchange(signUrl, HttpMethod.GET, httpEntity, String.class);
        return exchange.getBody();
    }

    /**
     * RestTemplate定义了36个与REST资源交互的方法，其中的大多数都对应于HTTP的方法。
     * 其实，这里面只有11个独立的方法，其中有十个有三种重载形式，而第十一个则重载了六次，这样一共形成了36个方法。
     *
     * delete() 在特定的URL上对资源执行HTTP DELETE操作
     * exchange() 在URL上执行特定的HTTP方法，返回包含对象的ResponseEntity，这个对象是从响应体中映射得到的
     * execute() 在URL上执行特定的HTTP方法，返回一个从响应体映射得到的对象
     * getForEntity() 发送一个HTTP GET请求，返回的ResponseEntity包含了响应体所映射成的对象
     * getForObject() 发送一个HTTP GET请求，返回的请求体将映射为一个对象
     * postForEntity() POST 数据到一个URL，返回包含一个对象的ResponseEntity，这个对象是从响应体中映射得到的
     * postForObject() POST 数据到一个URL，返回根据响应体匹配形成的对象
     * headForHeaders() 发送HTTP HEAD请求，返回包含特定资源URL的HTTP头
     * optionsForAllow() 发送HTTP OPTIONS请求，返回对特定URL的Allow头信息
     * postForLocation() POST 数据到一个URL，返回新创建资源的URL
     * put() PUT 资源到特定的URL
     *
     * GET参数说明：
     *
     * 第一个参数是url。
     * 第二个参数是返回值类型。
     * 第三个参数是uri地址路径变量。
     *
     * POST请求参数说明
     *
     * 第一个参数是url。
     * 第二个参数是请求参数。
     * 第三个参数是返回值类型。
     * 第三个参数是uri地址路径变量。
     *
     * PUT请求参数说明
     *
     * 第一个参数是url。
     * 第二个参数是请求参数。
     * 第三个参数是uri地址路径变量。
     *
     * DELETE请求参数说明
     *
     * 第一个参数是url
     * 第二个参数uri地址路径变量。
     *
     * exchange参数说明：
     *
     * 第一个参数是url。
     * 第二个参数是请求方式。
     * 第三个参数是请求实体。
     * 第四个参数是返回值类型。
     * 第五个参数是uri地址变量。
     *
     */
}
